#include<iostream>
#include<mutex>
using namespace std;

//
//
//namespace ns_test {
//	template<class T>
//	class shared_ptr {
//	public:
//		shared_ptr(T* ptr=nullptr)
//			:_ptr(ptr),_pcount(new int(1)),_mutex(new mutex)
//		{
//			cout << "shared_ptr()" << endl;
//		}
//
//		shared_ptr(const shared_ptr<T>& sp)
//			:_ptr(sp._ptr), _pcount(sp._pcount), _mutex(sp._mutex)
//		{
//			AddCount();
//		}
//
//		shared_ptr<T>& operator=(const shared_ptr<T>& sp) {
//			if (_ptr != sp._ptr) {
//				Release();
//				_ptr = sp._ptr;
//				_pcount = sp._pcount;
//				_mutex = sp._mutex;
//
//				AddCount();
//			}
//			return *this;
//		}
//		void Release() {
//			_mutex->lock();
//			bool flag = false;
//			if (--(*_pcount) == 0) {
//				delete _pcount;
//				delete _ptr;
//				flag = true;
//				cout << "Release()" << endl;
//			}
//			_mutex->unlock();
//			if (flag)
//				delete _mutex;
//		}
//
//		void AddCount() {
//			_mutex->lock();
//			++(*_pcount);
//			_mutex->unlock();
//		}
//
//		T& operator*() {
//			return *_ptr;
//		}
//
//		T* operator->() {
//			return _ptr;
//		}
//
//		~shared_ptr() {
//			Release();
//		}
//	private:
//		mutex* _mutex;
//		int* _pcount;
//		T* _ptr;
//	};
//
//	void test() {
//		shared_ptr<int> sp1(new int(1));
//		shared_ptr<int> sp2(sp1);
//		shared_ptr<int> sp3(new int(3));
//		cout << *sp1 << " " << *sp2 << " " << *sp3 << endl;
//		sp3 = sp1;
//		cout << *sp1 << " " << *sp2<<" " << *sp3 << endl;
//
//	}
//}
//
//int main() {
//	ns_test::test();
//	return 0;
//}


//class A {
//public:
//	static A* GetInstance() {
//		return &_instance;
//	}
//	int _n = 0;
//private:
//	A() {
//		cout << "A()" << endl;
//	}
//	A(const A&) = delete;
//	A operator=(const A&) = delete;
//
//	static A _instance;
//};
//
//A A::_instance;
//
//int main() {
//	cout << "-----------" << endl;
//	cout << A::GetInstance()->_n++ << endl;
//	cout << "-----------" << endl;
//	cout << A::GetInstance()->_n << endl;
//	return 0;
//}

class B {
public:
	static B* GetInstance() {
		if (_instance == nullptr) {
			std::unique_lock<mutex> lock(_mutex);
			if (_instance == nullptr) {
				_instance = new B();
			}
		}
		return _instance;
	}
	int _n = 0;

	class gc {
	public:
		~gc() {
			if (_instance)
				delete _instance;
		}
	};

	static gc _gc;
private:

	B() {
		cout << "B()" << endl;
	}
	B(const B&) = delete;
	B operator=(const B&) = delete;

	static B *_instance;
	static mutex _mutex;
};

B* B::_instance=nullptr;
mutex B::_mutex;
B::gc _gc;
